package com.xdcplus.web.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xdcplus.mom.constants.NumberConstant;
import com.xdcplus.mom.enums.ResponseEnum;
import com.xdcplus.exceptions.XdcWebException;

import java.util.*;

import cn.hutool.core.collection.CollectionUtil;

import com.xdcplus.mp.service.impl.BaseServiceImpl;
import com.xdcplus.web.common.pojo.entity.ToolProductionLineMain;
import com.xdcplus.web.common.pojo.vo.*;
import com.xdcplus.web.mapper.ToolProductionLineMainMapper;
import com.xdcplus.web.mapper.ToolProductionLineOpeMapper;
import com.xdcplus.web.common.pojo.entity.ToolProductionLineOpe;
import com.xdcplus.web.common.pojo.dto.ToolProductionLineOpeDTO;
import com.xdcplus.web.common.pojo.dto.ToolProductionLineOpeFilterDTO;
import com.xdcplus.web.common.pojo.query.ToolProductionLineOpeQuery;
import com.xdcplus.web.mapper.ToolProductionLineToolMapper;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageInfo;
import com.xdcplus.core.utils.BeanUtils;
import com.xdcplus.pager.vo.PageVO;
import com.xdcplus.mp.utils.PageableUtils;
import com.xdcplus.mp.utils.PropertyUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.stream.Collectors;

import com.xdcplus.web.service.ToolProductionLineOpeService;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.client.RestTemplate;

/**
 * (ToolProductionLineOpe)表服务实现类
 *
 * @author Man.Chen
 * @since 2024-12-03 16:40:35
 */
@Slf4j
@Service("toolProductionLineOpeService")
public class ToolProductionLineOpeServiceImpl extends BaseServiceImpl<ToolProductionLineOpeMapper, ToolProductionLineOpe, ToolProductionLineOpe, ToolProductionLineOpeVO> implements ToolProductionLineOpeService {

    @Autowired
    protected ToolProductionLineOpeMapper toolProductionLineOpeMapper;

    @Autowired
    private ToolProductionLineMainMapper toolProductionLineMainMapper;

    @Autowired
    private ToolProductionLineToolMapper toolProductionLineToolMapper;

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean saveToolProductionLineOpe(ToolProductionLineOpeDTO toolProductionLineOpeDTO) {

        ToolProductionLineOpe toolProductionLineOpe = new ToolProductionLineOpe();
        BeanUtil.copyProperties(toolProductionLineOpeDTO, toolProductionLineOpe);
//        toolProductionLineOpe.setCreatedTime(new Timestamp(DateUtil.current()));
        
        return this.save(toolProductionLineOpe);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean updateToolProductionLineOpe(ToolProductionLineOpeDTO toolProductionLineOpeDTO) {

        ToolProductionLineOpe toolProductionLineOpe = this.getById(toolProductionLineOpeDTO.getId());
        if (ObjectUtil.isNull(toolProductionLineOpe)) {
            log.error("updateToolProductionLineOpe() The ToolProductionLineOpe does not exist or has been deleted");
            throw new XdcWebException(ResponseEnum.ERROR);
        }

        BeanUtil.copyProperties(toolProductionLineOpeDTO, toolProductionLineOpe);
//        toolProductionLineOpe.setUpdateUser(toolProductionLineOpeDTO.getUpdatedUser());
//        toolProductionLineOpe.setUpdateTime(new Timestamp(DateUtil.current()));

        return this.updateById(toolProductionLineOpe);
    }

    @Override
    public List<Long> saveOrUpdateBatch(List<ToolProductionLineOpe> toolProductionLineOpeList) {

        toolProductionLineOpeList.forEach(toolProductionLineOpe -> {
            ToolProductionLineOpe toolProductionLineOpeParam = new ToolProductionLineOpe();
            toolProductionLineOpeParam.setId(toolProductionLineOpe.getId());
            if (ObjectUtil.isNotNull(toolProductionLineOpe.getId())) {
                toolProductionLineOpe.setId(toolProductionLineOpe.getId());
//                toolProductionLineOpe.setUpdateTime(new Timestamp(DateUtil.current()));
                LambdaUpdateWrapper<ToolProductionLineOpe> lambdaUpdate = Wrappers.lambdaUpdate();
                lambdaUpdate.eq(ToolProductionLineOpe::getId, toolProductionLineOpe.getId());
                update(toolProductionLineOpe, lambdaUpdate);
            } else {
//                toolProductionLineOpe.setCreateTime(new Timestamp(DateUtil.current()));
                save(toolProductionLineOpe);
            }
        });
        return toolProductionLineOpeList.stream()
                .map(ToolProductionLineOpe::getId)
                .collect(Collectors.toList());
    }

    @Override
    public List<Long> saveOrUpdateBatchByDTOList(List<ToolProductionLineOpeDTO> toolProductionLineOpeDTOList) {

        List<ToolProductionLineOpe> toolProductionLineOpeList = BeanUtils.copyProperties(toolProductionLineOpeDTOList, ToolProductionLineOpe.class);
        saveOrUpdateBatch(toolProductionLineOpeList);
        List<Long> opeIdList = Collections.emptyList();
        if (toolProductionLineOpeList != null) {
            opeIdList = toolProductionLineOpeList.stream()
                    .map(ToolProductionLineOpe::getId)
                    .collect(Collectors.toList());
        }

        return opeIdList;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean deleteToolProductionLineOpeLogical(Long id) {

        Assert.notNull(id, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());

        ToolProductionLineOpe toolProductionLineOpe = this.getById(id);

        if (ObjectUtil.isNull(toolProductionLineOpe)) {
            log.error("deleteToolProductionLineOpe() The ToolProductionLineOpe does not exist or has been deleted");
            throw new XdcWebException(ResponseEnum.ERROR);
        }
        return this.removeById(id);
    }
    
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean deleteToolProductionLineOpeByIds(String ids) {
        Assert.notNull(ids, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());
		List<String> idList = Arrays.asList(ids.split(","));
		if(CollectionUtil.isEmpty(idList)){
           throw new XdcWebException(ResponseEnum.ERROR);
       }
		idList.forEach(id->{
			ToolProductionLineOpe toolProductionLineOpe = this.getById(id);
			if (ObjectUtil.isNull(toolProductionLineOpe)) {
				log.error("deleteToolProductionLineOpe() The ToolProductionLineOpe does not exist or has been deleted");
				throw new XdcWebException(ResponseEnum.ERROR);
			}
		});
		
        return this.removeByIds(idList);
    }

    private List<ToolProductionLineOpe> queryToolProductionLineOpeList(ToolProductionLineOpeFilterDTO toolProductionLineOpeFilterDTO) {
        ToolProductionLineOpeQuery toolProductionLineOpeQuery = BeanUtil.copyProperties(toolProductionLineOpeFilterDTO, ToolProductionLineOpeQuery.class);

        return toolProductionLineOpeMapper.queryToolProductionLineOpe(toolProductionLineOpeQuery);
    }

    @Override
    public List<ToolProductionLineOpeVO> queryToolProductionLineOpeVOList(ToolProductionLineOpeFilterDTO toolProductionLineOpeFilterDTO) {
        return this.objectConversion(queryToolProductionLineOpeList(toolProductionLineOpeFilterDTO));
    }

    @Override
    public PageVO<ToolProductionLineOpeVO> queryToolProductionLineOpe(ToolProductionLineOpeFilterDTO toolProductionLineOpeFilterDTO) {
        PageVO<ToolProductionLineOpeVO> pageVO = new PageVO<>();

        if (toolProductionLineOpeFilterDTO.getCurrentPage() > NumberConstant.ZERO) {
            PageableUtils.basicPage(toolProductionLineOpeFilterDTO.getCurrentPage(), toolProductionLineOpeFilterDTO.getPageSize(),
                    toolProductionLineOpeFilterDTO.getOrderType(), toolProductionLineOpeFilterDTO.getOrderField());
        }

        List<ToolProductionLineOpe> toolProductionLineOpeList = queryToolProductionLineOpeList(toolProductionLineOpeFilterDTO);

        PageInfo<ToolProductionLineOpe> pageInfo = new PageInfo<>(toolProductionLineOpeList);
        PropertyUtils.copyProperties(pageInfo, pageVO, this.objectConversion(toolProductionLineOpeList));

        return pageVO;
    }

    @Override
    public ToolProductionLineOpeVO queryToolProductionLineOpeById(Long id) {

        Assert.notNull(id, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());

        return this.objectConversion(this.getById(id));
    }

    @Override
    public ToolDmIvSummaryVO queryElectricityPerformanceReport(Long mainId){
        ToolProductionLineMain toolProductionLineMain = toolProductionLineMainMapper.selectById(mainId);
        List<ToolProductionLineOpeVO> toolProductionLineOpeVOS = toolProductionLineOpeMapper.findOpesByMainId(Collections.singletonList(mainId));

        List<Long> opeIds = toolProductionLineOpeVOS.stream()
                .filter(ope -> "CSFX".equals(ope.getOpeCode()))
                .map(ToolProductionLineOpeVO::getId)
                .collect(Collectors.toList());

        if(opeIds.isEmpty()){
            log.error("queryElectricityPerformanceReport() 没有该工序");
            return null;
        }

        List<ToolProductionLineToolVO> toolProductionLineToolVOS = toolProductionLineToolMapper.findToolsByOpeId(opeIds);

        if (toolProductionLineToolVOS.isEmpty()){
            log.error("queryElectricityPerformanceReport() 没有该设备");
            return null;
        }

        List<String> bayCode = toolProductionLineToolVOS.stream()
                .map(ToolProductionLineToolVO::getLineNo)
                .collect(Collectors.toList());
        String startDate = DateUtil.format(toolProductionLineMain.getStartDate(), "yyyy-MM-dd HH:mm:ss");
        String endDate = DateUtil.format(toolProductionLineMain.getEndDate(), "yyyy-MM-dd HH:mm:ss");
        String authorization = getAuthorization();
        Map<String,Object> paramMap = new HashMap<>();
        List<String> proSpec = new ArrayList<>();
        proSpec.add(toolProductionLineMain.getMaterialCode());
        paramMap.put("startDate",startDate);
        paramMap.put("endDate",endDate);
        paramMap.put("proSpec",proSpec);
        paramMap.put("bayCode",bayCode);
        JsonNode jsonNode = makeApiCallDXL(paramMap, authorization);
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            List<ToolDmIvSummarySum> bayList = new ArrayList<>();
            List<ToolDmIvSummarySum> hourList = new ArrayList<>();
            List<ToolDmIvSummaryHourVO> hourBayList = new ArrayList<>();

            // 处理 bayList
            for (JsonNode itemNode : jsonNode.get("bayList")) {
                String item = itemNode.get("item").asText();
                List<ToolDmIvSummaryItemVO> itemList = new ArrayList<>();
                for (JsonNode itemListNode : itemNode.get("itemList")) {
                    ToolDmIvSummaryItemVO itemListObj = objectMapper.treeToValue(itemListNode, ToolDmIvSummaryItemVO.class);
                    itemList.add(itemListObj);
                }
                ToolDmIvSummarySum toolDmIvSummarySum = new ToolDmIvSummarySum();
                toolDmIvSummarySum.setItem(item);
                toolDmIvSummarySum.setItemList(itemList);
                bayList.add(toolDmIvSummarySum);
            }

            // 处理 hourList
            for (JsonNode hourNode : jsonNode.get("hourList")) {
                ToolDmIvSummarySum toolDmIvSummarySum = objectMapper.treeToValue(hourNode, ToolDmIvSummarySum.class);
                hourList.add(toolDmIvSummarySum);
            }

            // 处理 hourBayList
            for (JsonNode hourBayNode : jsonNode.get("hourBayList")) {
                List<ToolDmIvSummaryBayVO> bayListItems = new ArrayList<>();
                for (JsonNode bayListNode : hourBayNode.get("bayList")) {
                    ToolDmIvSummaryBayVO bayListItem = objectMapper.treeToValue(bayListNode, ToolDmIvSummaryBayVO.class);
                    bayListItems.add(bayListItem);
                }
                ToolDmIvSummaryHourVO toolDmIvSummaryHourVO = new ToolDmIvSummaryHourVO();
                toolDmIvSummaryHourVO.setBayList(bayListItems);
                hourBayList.add(toolDmIvSummaryHourVO);
            }

            ToolDmIvSummaryVO toolDmIvSummaryVO = new ToolDmIvSummaryVO();
            toolDmIvSummaryVO.setBayList(bayList);
            toolDmIvSummaryVO.setHourList(hourList);
            toolDmIvSummaryVO.setHourBayList(hourBayList);

            return toolDmIvSummaryVO;
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }


    public JsonNode makeApiCallDXL(Map<String, Object> paramMap, String authorization){
        RestTemplate restTemplate = new RestTemplate();
        ObjectMapper objectMapper = new ObjectMapper();

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", authorization);

        HttpEntity<String> entity = null;
        try {
            entity = new HttpEntity<>(objectMapper.writeValueAsString(paramMap), headers);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        try {
            ResponseEntity<String> response = restTemplate.postForEntity(
                    "http://172.16.34.71:83/api/mes-report-api/dmIvSummary/findDmIvSummaryByHour",
                    entity,
                    String.class
            );

            int statusCode = response.getStatusCodeValue();
            if (statusCode == 200) {
                String responseBody = response.getBody();
                if (responseBody != null) {
                    return objectMapper.readTree(responseBody).get("data");
                }
            } else {
                System.out.println("请求失败，状态码: " + statusCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    public String getAuthorization() {
        String loginUrl = "http://172.16.34.71/api/permission/basicLogin";
        String json = "{\"account\": \"135873\",\"password\": \"123456\"}";

        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity<String> requestEntity = new HttpEntity<>(json, headers);

        try {
            ResponseEntity<String> response = restTemplate.postForEntity(loginUrl, requestEntity, String.class);
            int statusCode = response.getStatusCodeValue();
            if (statusCode == 200) {
                String authorizationValue = response.getHeaders().getFirst("authorization");
                if (authorizationValue != null) {
                    System.out.println("authorization: " + authorizationValue);
                    return authorizationValue;
                } else {
                    System.out.println("未找到authorization字段");
                }
            } else {
                System.out.println("登录请求失败，状态码: " + statusCode);
            }
        } catch (Exception e) {
            System.out.println("登录请求失败: " + e.getMessage());
        }
        return null;
    }
}
